import java.util.*;


public class Set {

	int size = -1;
	int tagCompares = 0;
	
	//the only policy I care about is the replacement policy
	String policy;
	ArrayList<Block> myBlocks;
	ArrayList<Boolean> validBits;

	//this is the block most recently accessed. Used to make writing after a lookup easy.
	Block current;
	
	Random rand;
	
	Set(int s, String pol)
	{
		size = s;
		policy = pol;
		
		myBlocks = new ArrayList<Block>(size);
		validBits = new ArrayList<Boolean>(size);
		
		for(int i = 0; i < size; i++)
		{
			validBits.add(new Boolean(false));
		}
		
		rand = new Random();
	}
	
	//NOTE it will load the block, even if it already exists in the set!
	//it's cache's job to check that for now...
	void load(Block b)
	{
		if(myBlocks.size() < size)
		{
			//empty slots? Fill em!
			myBlocks.add(b);
			validBits.set(myBlocks.indexOf(b), new Boolean(true));
		}
		else
		{
			//we need to replace something
			//dirty bit usage??
			
			//R = Random replace
			if(policy.equalsIgnoreCase("R"))
				myBlocks.set(rand.nextInt(size), b);
			
			//FIFO = Queue
			else if(policy.equalsIgnoreCase("FIFO"))
			{
				myBlocks.remove(0);
				myBlocks.add(b);
			}
			
			//LRU = Least Recently Used block is replaced
			else if(policy.equalsIgnoreCase("LRU"))
			{
				int temp = findLRU();
				myBlocks.set(temp, b);
			}
			else
			{
				System.out.println("Bad replacement policy!");
			}
		}
	}
	
	private int findLRU()
	{
		int oldestIndex = 0;
		
		for(int i = 0; i < myBlocks.size(); i++)
		{
			Date oldestDate = myBlocks.get(oldestIndex).getDate();
			Date iDate      = myBlocks.get(          i).getDate();
			
			if( iDate.before(oldestDate))
				oldestIndex = i;
		}
		
		return oldestIndex;
	}
	
	void write()
	{
		current.setDirty(true);
	}
	
	//does this set contain this tag? The Cache has determined that if anyone has it, I have it...
	boolean find(long tag)
	{
		boolean flag = false;
		
		for(int i = 0; i < myBlocks.size(); i++)
		{
			Block temp = myBlocks.get(i);
			
			tagCompares += 1;
			if(temp.getTag() == tag)
			{
				flag = true;
				current = temp;
				current.updateLastUsed();
				break;
			}
		}
		
		return flag;
	}
}
